import UIKit

// 蛇
class Snake {
    private var mCauda: SnakeBody!                              // 蛇尾
    private var mDirection: UISwipeGestureRecognizer.Direction  // 移动方向
    private var mHead: SnakeBody                                // 蛇头

    /**
     * 构造方法。
     * @param drawer    绘图者
     */
    public init(_ drawer: CGContext) {
        // 初始化成员
        let caudaPos = CGPoint(x: 0, y: 0)
        mCauda = SnakeBody(drawer, point: caudaPos, type: .SNAKE)
        mDirection = .down
        mHead = mCauda
    }

    /**
     * 吃果子，即将果子放到蛇尾。
     * @param apple 果子
     */
    public func eat(_ apple: SnakeBody!) {
        // 设置吃到的果子的位置
        var position = CGPoint(x: mHead.position.x, y: mHead.position.y)
        switch mDirection {
            case .down:
                position.y += 1
            case .left:
                position.x -= 1
            case .right:
                position.x += 1
            case .up:
                position.y -= 1
            default:
                break
        }
        apple.position = position
        
        // 改变果子的类型
        apple.setType(.SNAKE)
        
        // 重绘蛇头和果子
        mHead.draw()
        apple.draw()
        
        // 将吃到的果子变成蛇头
        mHead.next = apple
        mHead = apple
    }
    
    /**
     * 获取蛇头。
     */
    public var head: SnakeBody {
        get {
            return mHead
        }
    }

    /**
     * 移动。
     * @return 蛇头碰到自身或游戏区域边界则返回 true，否则返回 false
     */
    public func move() -> Bool {
        // 计算蛇尾的新位置并抹除蛇尾
        var point = CGPoint(x: mHead.position.x, y: mHead.position.y)
        switch mDirection {
            case .down:
                if mHead.position.y + 1 >= Const.GAME_BOARD_GRID_COUNT_V {
                    // 如果蛇头超出游戏区域下边界，则返回
                    return true
                }
                mCauda.erase()
                point.y += 1
            case .left:
                if mHead.position.x - 1 < 0 {
                    // 如果蛇头超出游戏区域左边界，则返回
                    return true
                }
                mCauda.erase()
                point.x -= 1
            case .right:
                if mHead.position.x + 1 >= Const.GAME_BOARD_GRID_COUNT_H {
                    // 如果蛇头超出游戏区域右边界，则返回
                    return true
                }
                mCauda.erase()
                point.x += 1
            case .up:
                if mHead.position.y - 1 < 0 {
                    // 如果蛇头超出游戏区域上边界，则返回
                    return true
                }
                mCauda.erase()
                point.y -= 1
            default:
                break
        }

        mCauda.position = point

        // 将蛇尾的下一个结点设置为蛇尾、原蛇尾设置成蛇头
        mHead.next = mCauda
        mHead = mCauda
        mCauda = mCauda.next
        mHead.next = nil
        mHead.draw()

        // 检查蛇头是否碰到蛇身
        var snakeBody = mCauda!
        while snakeBody != mHead {
            if snakeBody.position == mHead.position {
                return true
            }
            snakeBody = snakeBody.next!
        }
        return false
    }

    /**
     * 检查某点是否与蛇身位置重叠。
     * @param point 被检查的点
     * @return 点与蛇身位置重叠则返回 true ，否则返回 false
     */
    public func pointIsOnMe(_ point: CGPoint) -> Bool {
        var snakeBody = mCauda
        while snakeBody != nil {
            if snakeBody!.position == point {
                return true
            }
            snakeBody = snakeBody!.next
        }
        return false
    }

    /**
     * 转弯。
     * @param direction 方向
     */
    public func turn(_ direction: UISwipeGestureRecognizer.Direction) {
        // 如果方向与当前方向相反(想要直接调头)，则直接返回
        if direction == .left && mDirection == .right ||
            direction == .right && mDirection == .left ||
            direction == .up && mDirection == .down ||
            direction == .down && mDirection == .up {
            return
        }
        mDirection = direction
    }
}
